package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.ChromeOSOnly
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

////////////////////
// Audio
////////////////////
/**
 * The `Browser.audio` API is provided to allow users to get information about and control the audio devices attached to the system. This API is currently only available in kiosk mode for ChromeOS.
 *
 * Permissions: "audio"
 * @platform ChromeOS only
 * @since Chrome 59
 */
@ChromeOSOnly
@ChromeMinVersion(59)
interface Audio {

    // Gets a Array of audio devices filtered based on filter.
    // Promises are only supported for Manifest V3 and later, other platforms need to use callbacks.
    @PromiseStyleMinVersion(116)
     fun getDevices(
        // Device properties by which to filter the Array of returned audio devices.
        // If the filter is not set or set to {}, returned device Array will contain all available audio devices.
        filter: DeviceFilter? = null,
        // @params {callback.devices}
        callback: Value1Function<List<AudioDeviceInfo>>? = null
    ): Promise<List<AudioDeviceInfo>>

    // Gets the system-wide mute state for the specified stream type.
    @PromiseStyleMinVersion(116)
     fun getMute(
        streamType: StreamType,
        // @params {callback.value}
        callback: Value1Function<Boolean>? = null
    ): Promise<Boolean>

    // Sets lists of active input and/or output devices.
    @PromiseStyleMinVersion(116)
     fun setActiveDevices(
        // Specifies IDs of devices that should be active.
        // If either the input or output Array is not set, devices in that category are unaffected.
        //
        //It is an error to pass in a non-existent device ID.
        ids: DeviceIdLists,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Sets mute state for a stream type. The mute state will apply to all audio devices with the specified audio stream type.
    @PromiseStyleMinVersion(116)
     fun setMute(
        streamType: StreamType,
        isMuted: Boolean,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Sets the properties for the input or output device.
    @PromiseStyleMinVersion(116)
     fun setProperties(
        id: String,
        properties: DeviceProperties,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Fired when audio devices change, either new devices being added, or existing devices being removed.
     var onDeviceListChanged: Events.Event<Value1Function<List<AudioDeviceInfo>>>

    // Fired when sound level changes for an active audio device.
     var onLevelChanged: Events.Event<Value1Function<LevelChangedEvent>>

    // Fired when the mute state of the audio input or output changes.
    // Note that mute state is system-wide and the new value applies to every audio device with specified stream type.
     var onMuteChanged: Events.Event<Value1Function<MuteChangedEvent>>

    data class AudioDeviceInfo(
        // Device name.
        var deviceName: String,
        // Type of the device.
        var deviceType: DeviceType,
        // The user-friendly name (e.g. "USB Microphone").
        var displayName: String,
        // The unique identifier of the audio device.
        var id: String,
        // True if this is the current active device.
        var isActive: Boolean,
        // The sound level of the device, volume for output, gain for input.
        var level: Number,
        // The stable/persisted device id string when available.
        var stableDeviceId: String? = null,
        // Stream type associated with this device.
        var streamType: StreamType
    )

    data class DeviceFilter(
        // If set, only audio devices whose active state matches this value will satisfy the filter.
        var isActive: Boolean? = null,
        // If set, only audio devices whose stream type is included in this Array will satisfy the filter.
        var streamTypes: List<StreamType>? = null
    )

    data class DeviceIdLists(
        // Array of input devices specified by their ID.
        //
        //To indicate input devices should be unaffected, leave this property unset.
        var input: List<String>? = null,
        // Array of output devices specified by their ID.
        //
        //To indicate output devices should be unaffected, leave this property unset.
        var output: List<String>? = null
    )

    data class DeviceProperties(
        // The audio device's desired sound level. Defaults to the device's current sound level.
        //
        //If used with audio input device, represents audio device gain.
        //
        //If used with audio output device, represents audio device volume.
        var level: Number? = null
    )

    data class LevelChangedEvent(
        // ID of device whose sound level has changed.
        var deviceId: String,
        // The device's new sound level.
        var level: Number,
    )

    data class MuteChangedEvent(
        // Whether or not the stream is now muted.
        var isMuted: Boolean,
        // The type of the stream for which the mute value changed. The updated mute value applies to all devices with this stream type.
        var streamType: StreamType
    )

    enum class DeviceType {
        HEADPHONE,
        MIC,
        USB,
        BLUETOOTH,
        HDMI,
        INTERNAL_SPEAKER,
        INTERNAL_MIC,
        FRONT_MIC,
        REAR_MIC,
        KEYBOARD_MIC,
        HOTWORD,
        LINE_OUT,
        POST_MIX_LOOPBACK,
        POST_DSP_LOOPBACK,
        ALSA_LOOPBACK,
        OTHER
    }

    enum class StreamType {
        INPUT,
        OUTPUT
    }

}
